#include "jsdl.h"
#include <SDL.h>
#include <iostream>
using namespace std;
JSDL::JSDL() {}

static bool InitVideo()
{
    static bool is_first = true;
    static mutex mux;
    std::unique_lock<std::mutex> lock(mux);
    if(!is_first) return true;
    is_first = false;


    if(SDL_Init(SDL_INIT_VIDEO))
    {
        cout<<SDL_GetError()<<endl;
        return false;
    }
    //设定缩放算法，解决锯齿问题
    SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY,"1");
    return  true;
}
bool JSDL::Init(int w, int h, Format fmt)
{
    if(w<=0 || h<=0)
    {
        return false;
    }
    //初始化SDL 视频库
    InitVideo();


    //加锁的目的是为了防止 窗口大小的改变和渲染同时发生，会引起内存冲突
    std::unique_lock<std::mutex> lock(mtx_);
    width_ = w;
    height_ = h;
    fmt_ = fmt;

    if(render_)
        SDL_DestroyRenderer(render_);
    if(texture_)
        SDL_DestroyTexture(texture_);
    if(!win_)
    {
        if(!win_id_)
        {
            win_ = SDL_CreateWindow("",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,w,h,SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE|SDL_WINDOW_SHOWN);
        }
        else
        {
            win_ = SDL_CreateWindowFrom(win_id_);
        }
    }
    if(!win_)
    {
        cerr<<SDL_GetError()<<endl;
    }


    //创建渲染器

    render_ = SDL_CreateRenderer(win_,-1,SDL_RENDERER_ACCELERATED);
    if(!render_)
    {
        cerr<<SDL_GetError()<<endl;
        return false;
    }
    unsigned int sdl_fmt = SDL_PIXELFORMAT_RGBA8888;
    switch(fmt_)
    {
    case JVideoView::RGBA:
        sdl_fmt = SDL_PIXELFORMAT_RGBA32;
        break;
    case JVideoView::BGRA:
        sdl_fmt = SDL_PIXELFORMAT_BGRA32;
        break;
    case JVideoView::ARGB:
        sdl_fmt = SDL_PIXELFORMAT_ARGB32;
        break;
    case JVideoView::YUV420P:
        sdl_fmt = SDL_PIXELFORMAT_IYUV;
        break;
    default:
        break;
    }

    texture_ = SDL_CreateTexture(render_,
                      sdl_fmt,
                      SDL_TEXTUREACCESS_STREAMING,//频繁修改的渲染
                      w,h//材质大小
                      );
    if(!texture_)
    {
        cerr<<SDL_GetError()<<endl;
        return false;
    }
    return true;
}

bool JSDL::Draw(const unsigned char *data, int linesize)
{
    if(!data)
    {
        return false;
    }
    std::unique_lock<std::mutex> lock(mtx_);
    if(!texture_ || !render_ || !win_ || width_<=0 ||height_ <= 0)
        return false;



    if(linesize<=0)
    {
        switch(fmt_)
        {
        case JVideoView::RGBA:
        case JVideoView::ARGB:
            linesize = width_*4;
            break;
        case JVideoView::YUV420P:
            linesize = width_;
            break;
        default:
            break;
        }
    }
    if(linesize<0) return false;

    //复制内存数据到显存
    int re = SDL_UpdateTexture(texture_,NULL,data,linesize);
    if(re!=0)
    {
        cout<<SDL_GetError()<<endl;
        return false;
    }
    SDL_RenderClear(render_);
    if(scale_w_ <= 0) scale_w_ = width_;
    if(scale_h_ <= 0) scale_h_ = height_;
    SDL_Rect rect;
    rect.x=0;
    rect.y=0;
    rect.w=scale_w_;
    rect.h=scale_h_;
    re = SDL_RenderCopy(render_,texture_,NULL,&rect);
    if(re!=0)
    {
        cout<<SDL_GetError()<<endl;
    }
    SDL_RenderPresent(render_);
    return true;
}

bool JSDL::Draw(const unsigned char *y, int y_pitch, const unsigned char *u, int u_pitch, const unsigned char *v, int v_pitch)
{
    if(!y || !u ||!v)
    {
        return false;
    }
    std::unique_lock<std::mutex> lock(mtx_);
    if(!texture_ || !render_ || !win_ || width_<=0 ||height_ <= 0)
        return false;




    //复制内存数据到显存
    int re = SDL_UpdateYUVTexture(texture_,NULL,y,y_pitch,u,u_pitch,v,v_pitch);
    if(re!=0)
    {
        cout<<SDL_GetError()<<endl;
        return false;
    }
    SDL_RenderClear(render_);
    if(scale_w_ <= 0) scale_w_ = width_;
    if(scale_h_ <= 0) scale_h_ = height_;
    SDL_Rect rect;
    rect.x=0;
    rect.y=0;
    rect.w=scale_w_;
    rect.h=scale_h_;
    re = SDL_RenderCopy(render_,texture_,NULL,&rect);
    if(re!=0)
    {
        cout<<SDL_GetError()<<endl;
    }
    SDL_RenderPresent(render_);
    return true;
}

bool JSDL::isExit()
{
    SDL_Event ev;
    SDL_WaitEventTimeout(&ev,1);
    if(ev.type==SDL_QUIT)
        return true;
    return false;
}

void JSDL::Close()
{
    std::unique_lock<std::mutex> lock(mtx_);
    if(texture_)
    {
        SDL_DestroyTexture(texture_);
        texture_ = nullptr;
    }
    if(render_)
    {
        SDL_DestroyRenderer(render_);
        render_ = nullptr;
    }
    if(win_)
    {
        SDL_DestroyWindow(win_);
        win_ = nullptr;
    }
}

